home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Developer Helper 1: Phil & Dave's Excellent CD
/
Excellent CD HFS.raw
/
Moof
/
Goodies
/
DTS Goodies
/
Bechtels stuff
/
Play.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-08-29
|
12KB
|
454 lines
/* File: Play.c
* Purpose: demonstrate Apple CD SC control
* Date: 17 June 1988
* Comments:
* This code is written for LightSpeed C version 2.15
* Create a project with this source plus MacTraps.
* Requires some associated resources (in the file Play.r).
* With this program on your hard disk, you can click
* on a track on an Audio CD and the CD SC drive will
* start audio play, beginning at that track and continuing
* to the end of the disc.
*
* Revisions:
*
* Converted to converted to mpw 3.0 8/29 mb
*
* Build instructions:
*
* rez -c MBAU :RIncludes:Types.r Play.r -o Play
* c Play.c -w
* link Play.c.o -o Play -c aucd ∂
* "{CLibraries}"CRuntime.o ∂
* "{CLibraries}"CInterface.o ∂
* "{Libraries}"Interface.o
*
*
*/
#include <types.h> /* Nearly always required */
#include <quickdraw.h> /* To access the qd globals */
#include <fonts.h> /* Only for InitFonts() trap */
#include <events.h> /* GetNextEvent(), ... */
#include <windows.h> /* GetNewWindow(), ... */
#include <dialogs.h> /* InitDialogs() and GetNewDialog() */
#include <menus.h> /* EnableItem(), DisableItem() */
#include <desk.h> /* SystemTask(), SystemClick() */
#include <TextEdit.h>
#include <Resources.h> /* GetResource() */
#include <OSUtils.h> /* SysBeep() */
#include <ToolUtils.h>
#include <SegLoad.h>
#include <Strings.h>
#include <Devices.h>
#include <Files.h>
#include <Packages.h>
#include <Memory.h>
#include <OSEvents.h>
/* Some constants, from the CD SC Developer's Guide chapter 7 */
#define TRACKADDR 2
#define STEREO 9
#define INPROGRESS 0
/* Some commands, from the CD SC Developer's Guide chapter 7 */
#define APLAY 104
#define ASTOP 106
#define ASTATUS 107
/* The resource ID I use for my error dialog */
#define errorID 128
/* prototype function declarations. */
void Error(char *, short);
void ExtractTrackNo(char *, short *);
OSErr AStop(short, short);
OSErr APlay(short, short);
OSErr Play(char *, short);
short GetDrvRefNum(short);
void PlayOnStartup(short);
Boolean AskAndPlay(void);
void main(void);
pascal void Debugger(/*void*/) extern 0xA9FF;
/************************************************************************
*
* Function: Error
*
* Purpose: Report an error to the user.
*
* Returns: nothing
*
* Side Effects: none.
*
* Description: Takes a string and a result code. Convert the result
* into a pascal string using NumToString() and then just
* do a switch to determine which friendly error message
* to put up on the screen. ParamText() sets up the alert
* so that it has the correct information. Use Alert() to
* actually display the message to the user.
*
************************************************************************/
void
Error(where, result)
char *where;
short result;
{
DialogPtr dPtr;
short itemhit;
Str255 strResult;
long longResult;
longResult = result;
NumToString(longResult, strResult);
switch (result)
{
case -56:
ParamText(where, strResult, "\pSpecified drive number doesn't match any number in the drive queue.", "\p");
break;
case -51:
ParamText(where, strResult, "\pReference number specifies nonexistent access path.", "\p");
break;
case -50:
ParamText(where, strResult, "\pError in parameter list.", "\p");
break;
case -43:
ParamText(where, strResult, "\pFile not found.", "\p");
break;
case -36:
ParamText(where, strResult, "\pI/O error.", "\p");
break;
case -35:
ParamText(where, strResult, "\pNo such volume.", "\p");
break;
case -21:
ParamText(where, strResult, "\pBad unit number.", "\p");
break;
default:
ParamText(where, strResult, "\p", "\p");
break;
}
Alert(errorID, (ProcPtr) NULL);
}
/************************************************************************
*
* Function: ExtractTrackNo
*
* Purpose: Extract track number in BCD from PString
*
* Returns: nothing
*
* Side Effects: *track gets a new value
*
* Description: Extract track number in BCD from PString "name".
* "name" is always of the form "Track XX", where XX
* ranges from " 1" (1 with a leading space) to "99"
* (You can't have more than 99 tracks on a compact disc.
* Bet you didn't know that, did you? Right in the "Yellow
* Book" specification of compact disc encoding.)
*
************************************************************************/
void
ExtractTrackNo(name, track)
char *name;
short *track;
{
short size;
short t;
t = 0;
size = *name;
if (name[size-1] != ' ')
t = (name[size-1] - '0') * 16;
t += name[size] - '0';
*track = t;
}
/************************************************************************
*
* Function: AStop
*
* Purpose: stop playing an audio track
*
* Returns: OSErr. Probably either
* noErr everything's hunky-dory!
* paramErr you messed up the call somehow.
*
* Side Effects: stops play.
*
* Description: The track that you pass in is the LAST track that you
* want to have play. This means that if you wanted to
* play only one track, you'd pass the same value to
* this routine and APlay() [q.v.]
*
* Note that this routine isn't called in this sample,
* but it's included for your enjoyment.
*
************************************************************************/
OSErr
AStop(track, refNum)
short track;
short refNum;
{
struct {
short addrFormat;
long address;
} csParam;
csParam.addrFormat = TRACKADDR;
csParam.address = track;
return (Control(refNum, ASTOP, &csParam));
}
/************************************************************************
*
* Function: APlay
*
* Purpose: start playing an audio track
*
* Returns: OSErr. Probably either
* noErr everything's hunky-dory!
* paramErr you messed up the call somehow.
*
* Side Effects: starts play. By default, this will play until the
* end of the disc.
*
* Description: The track that you pass in is the first track that you
* want to have play.
*
************************************************************************/
OSErr
APlay(track, refNum)
short track;
short refNum;
{
struct {
short addrFormat;
long address;
short stopAddress;
short playMode;
} csParam;
csParam.addrFormat = TRACKADDR;
csParam.address = track; /* must be in BCD */
csParam.stopAddress = 0;
csParam.playMode = STEREO;
return (Control(refNum, APLAY, &csParam));
}
/************************************************************************
*
* Function: Play
*
* Purpose: play a track, given it's "filename"
*
* Returns: OSErr
* whatever is returned by APlay()
*
* Side Effects: starts play of the audio track.
*
* Description: The two parameters passed in are the file name (which
* will always be of the form "Track XX", XX varying from
* " 1" to "99") and the driver reference number. Extract
* the track number and use it to call APlay() [q.v.]
*
************************************************************************/
OSErr
Play(name, driveNumber)
char *name;
short driveNumber;
{
short trackno;
OSErr result;
ExtractTrackNo(name, &trackno);
return( APlay(trackno, driveNumber) );
}
/************************************************************************
*
* Function: GetDrvRefNum
*
* Purpose: Get the driver reference number
*
* Returns: short. The driver reference number
*
* Side Effects: none.
*
* Description: PBHGetVInfo() will retrieve the driver reference
* number, given the vRefNum associated with a file.
* We acquired the vRefNum as something passed into
* the program, either by SFGetFile() or by
* GetAppFile().
*
* We'll use the driver reference number in all our
* control calls to the driver.
*
************************************************************************/
short
GetDrvRefNum(vRefNum)
short vRefNum;
{
HParamBlockRec io;
io.volumeParam.ioCompletion = NULL;
io.volumeParam.ioNamePtr = NULL;
io.volumeParam.ioVRefNum = vRefNum;
io.volumeParam.ioVolIndex = 0;
PBHGetVInfo(&io, false);
return io.volumeParam.ioVDRefNum;
}
/************************************************************************
*
* Function: PlayOnStartup
*
* Purpose: Play the files passed in to our application
*
* Returns: nothing
*
* Side Effects: plays some files.
*
* Description: Loop, using GetAppFiles() to get the next "file"
* (actually audio CD track) to play. Continue until
* we run out of files to play or until we get some
* error while trying to play a track.
*
* Exercise to the programmer:
* As this routine is currently written, it doesn't
* handle opening multiple tracks at once. (e.g. the
* user selects five tracks and opens them all.) Right
* now, you'll only hear the last track (each Play()
* command cancels the previous one.)
*
* Add a routine to check the status of the CD SC
* drive (using AStatus) so that you wait for a track
* to finish before starting the next track.
*
************************************************************************/
void
PlayOnStartup(count)
short count;
{
short i;
AppFile app;
OSErr result;
for (i = 0; i++<count; )
{
GetAppFiles(i, &app);
if (app.fType == 'trak')
{
result = Play((char *)app.fName, GetDrvRefNum(app.vRefNum));
if (result != noErr)
Error("\pPlay returned", result);
}
}
}
/************************************************************************
*
* Function: AskAndPlay
*
* Purpose: Prompt the user for a track and play it
*
* Returns: Boolean. Either:
* true the user wants us to continue
* false the user wants us to exit, or an error
* occurred.
*
* Side Effects: may play a track.
*
* Description: Use SFGetFile() with a specific type ('trak') to get
* a list of just audio CD tracks. If the user selects
* an audio CD track, play it.
*
************************************************************************/
Boolean
AskAndPlay()
{
SFReply sf;
short refnum;
static Point where = {100,100};
static OSType sftl = 'trak';
Boolean result;
OSErr errorCode;
result = true;
FlushEvents(everyEvent-diskMask,0);
SFGetFile(where, "\pSelect Track to Play", (ProcPtr)NULL,
1, &sftl, (ProcPtr)NULL, &sf);
if (!sf.good)
result = false;
else
{
errorCode = Play((char *)sf.fName, GetDrvRefNum(sf.vRefNum));
if (errorCode != noErr)
{
Error("\pPlay returned", result);
result = false;
}
}
return result;
}
/************************************************************************
*
* Function: main
*
* Purpose: The Master Cylinder. This is where we start.
*
* Returns: nothing.
*
* Side Effects: does whatever you tell it.
*
* Description: Do the standard Macintosh initialization. Following
* all the boilerplate, use CountAppFiles() to see how
* we were started. We could be started one of three
* ways:
* 1) The user opened our application. We will have
* a count of zero. Go ask the user for a track.
* 2) The user opened an audio CD track "file". We
* will have a non-zero count. Go play the track(s)
* that the user asked.
*
************************************************************************/
void
main()
{
short message, count;
short refNum;
MaxApplZone();
MoreMasters();
InitGraf(&qd.thePort);
InitFonts();
InitWindows();
InitMenus();
TEInit();
InitDialogs(0);
InitCursor();
FlushEvents(everyEvent-diskMask,0);
CountAppFiles(&message, &count);
if (count)
PlayOnStartup(count);
else
while (AskAndPlay())
; /* null loop */
}